Add 'faketime' option to track filter with test cases and doc.
authorrobertl <robertl>
Sat, 5 Jun 2010 22:02:39 +0000 (22:02 +0000)
committerrobertl <robertl>
Sat, 5 Jun 2010 22:02:39 +0000 (22:02 +0000)
reference/track/trackfilter_faketime.gpx [new file with mode: 0644]
reference/track/trackfilter_faketime.txt [new file with mode: 0644]
reference/track/trackfilter_faketime_forced.gpx [new file with mode: 0644]
testo.d/classic-2.test
testo.d/track.test [new file with mode: 0644]
trackfilter.c
xmldoc/filters/options/track-faketime.xml [new file with mode: 0644]

diff --git a/reference/track/trackfilter_faketime.gpx b/reference/track/trackfilter_faketime.gpx
new file mode 100644 (file)
index 0000000..bdbb131
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx
+  version="1.0"
+  creator="GPSBabel - http://www.gpsbabel.org"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://www.topografix.com/GPX/1/0"
+  xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
+<time>1970-01-01T00:00:00Z</time>
+<bounds minlat="36.000000000" minlon="-87.000000000" maxlat="36.000000000" maxlon="-87.000000000"/>
+<trk>
+<trkseg>
+<trkpt lat="36.000000000" lon="-87.000000000">
+  <time>2010-05-06T06:00:00Z</time>
+</trkpt>
+<trkpt lat="36.000000000" lon="-87.000000000">
+  <time>2008-04-17T00:00:00Z</time>
+</trkpt>
+<trkpt lat="36.000000000" lon="-87.000000000">
+  <time>2010-05-06T06:00:05Z</time>
+</trkpt>
+</trkseg>
+</trk>
+</gpx>
diff --git a/reference/track/trackfilter_faketime.txt b/reference/track/trackfilter_faketime.txt
new file mode 100644 (file)
index 0000000..f9aff17
--- /dev/null
@@ -0,0 +1,4 @@
+lat, lon, date
+36, -87
+36, -87, 2008-04-17
+36, -87
diff --git a/reference/track/trackfilter_faketime_forced.gpx b/reference/track/trackfilter_faketime_forced.gpx
new file mode 100644 (file)
index 0000000..b215439
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx
+  version="1.0"
+  creator="GPSBabel - http://www.gpsbabel.org"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns="http://www.topografix.com/GPX/1/0"
+  xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
+<time>1970-01-01T00:00:00Z</time>
+<bounds minlat="36.000000000" minlon="-87.000000000" maxlat="36.000000000" maxlon="-87.000000000"/>
+<trk>
+<trkseg>
+<trkpt lat="36.000000000" lon="-87.000000000">
+  <time>2010-05-06T06:00:00Z</time>
+</trkpt>
+<trkpt lat="36.000000000" lon="-87.000000000">
+  <time>2010-05-06T06:00:05Z</time>
+</trkpt>
+<trkpt lat="36.000000000" lon="-87.000000000">
+  <time>2010-05-06T06:00:10Z</time>
+</trkpt>
+</trkseg>
+</trk>
+</gpx>
index 79acbafdf7a115e327b4af0f54d5406d97e3cef7..9dba60b2b0164aa17b6e123d6b8c9d8b21f95361 100755 (executable)
@@ -342,21 +342,6 @@ compare ${TMPDIR}/vitosmt.gpx ${REFERENCE}/vitosmt.gpx
 gpsbabel -t -i vitosmt -f ${REFERENCE}/vitosmt.smt -o gpx -F ${TMPDIR}/vitosmt_t.gpx
 compare ${TMPDIR}/vitosmt_t.gpx ${REFERENCE}/track/vitosmt_t.gpx
 
-#
-# tracks filter tests
-#
-
-rm -f ${TMPDIR}/trackfilter*
-
-gpsbabel -t -i gpx -f ${REFERENCE}/track/trackfilter.gpx -x track,pack,split,title="LOG-%Y%m%d" -o gpx -F ${TMPDIR}/trackfilter.gpx
-compare ${TMPDIR}/trackfilter.gpx ${REFERENCE}/track/trackfilter.gpx
-
-gpsbabel -t -i gpx -f ${REFERENCE}/track/trackfilter.gpx -x track,pack,split,sdistance=0.1k  -o gpx -F ${TMPDIR}/trackfilter2.gpx
-compare ${TMPDIR}/trackfilter2.gpx ${REFERENCE}/track/trackfilter-sdistance.gpx
-
-gpsbabel -t -i gpx -f ${REFERENCE}/track/trackfilter.gpx -x track,pack,sdistance=0.1k,split=5m,title=%Y%m%d  -o gpx -F ${TMPDIR}/trackfilter-sdistance2.gpx
-compare ${TMPDIR}/trackfilter-sdistance2.gpx ${REFERENCE}/track/trackfilter-sdistance2.gpx
-
 #
 # Map&Guide Motorrad Routenplaner .bcr files test
 #
diff --git a/testo.d/track.test b/testo.d/track.test
new file mode 100644 (file)
index 0000000..65bdf11
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# tracks filter tests
+#
+
+rm -f ${TMPDIR}/trackfilter*
+
+gpsbabel -t -i gpx -f ${REFERENCE}/track/trackfilter.gpx -x track,pack,split,title="LOG-%Y%m%d" -o gpx -F ${TMPDIR}/trackfilter.gpx
+compare ${TMPDIR}/trackfilter.gpx ${REFERENCE}/track/trackfilter.gpx
+
+gpsbabel -t -i gpx -f ${REFERENCE}/track/trackfilter.gpx -x track,pack,split,sdistance=0.1k  -o gpx -F ${TMPDIR}/trackfilter2.gpx
+compare ${TMPDIR}/trackfilter2.gpx ${REFERENCE}/track/trackfilter-sdistance.gpx
+
+gpsbabel -t -i gpx -f ${REFERENCE}/track/trackfilter.gpx -x track,pack,sdistance=0.1k,split=5m,title=%Y%m%d  -o gpx -F ${TMPDIR}/trackfilter-sdistance2.gpx
+compare ${TMPDIR}/trackfilter-sdistance2.gpx ${REFERENCE}/track/trackfilter-sdistance2.gpx
+
+# Exercise the 'faketime' filter.  The middle of the three points has
+# time so we can exercise the 'forced' option, too.
+gpsbabel -t -i unicsv -f ${REFERENCE}/track/trackfilter_faketime.txt -x track,faketime=20100506060000+5 -o gpx -F ${TMPDIR}/ft.gpx 
+compare ${REFERENCE}/track/trackfilter_faketime.gpx ${TMPDIR}/ft.gpx
+gpsbabel -t -i unicsv -f ${REFERENCE}/track/trackfilter_faketime.txt -x track,faketime=f20100506060000+5 -o gpx -F ${TMPDIR}/ftf.gpx
+compare ${REFERENCE}/track/trackfilter_faketime_forced.gpx ${TMPDIR}/ftf.gpx
index bdc4551cc1bb5f70d3f3f928fa3897856c45382d..11f6875210caa1161e813b7f766641892fb63acb 100644 (file)
@@ -33,6 +33,7 @@
     2007-01-08: if not really needed disable check for valid timestamps
                (based on patch from Vladimir Kondratiev)
     2007-07-26: Allow 'range' together with trackpoints without timestamp
+    2010-06-02: Add specified timestamp to each trackpoint (added by sven_luzar)
  */
  
 #include <ctype.h>
@@ -59,6 +60,7 @@
 #define TRACKFILTER_SPEED_OPTION        "speed"
 #define TRACKFILTER_SEG2TRK_OPTION      "seg2trk"
 #define TRACKFILTER_TRK2SEG_OPTION      "trk2seg"
+#define TRACKFILTER_FAKETIME_OPTION     "faketime"
 
 #undef TRACKF_DBG
 
@@ -76,6 +78,7 @@ static char *opt_speed = NULL;
 static char *opt_name = NULL;
 static char *opt_seg2trk = NULL;
 static char *opt_trk2seg = NULL;
+static char *opt_faketime = NULL;
 
 static
 arglist_t trackfilter_args[] = {
@@ -117,6 +120,9 @@ arglist_t trackfilter_args[] = {
        {TRACKFILTER_TRK2SEG_OPTION, &opt_trk2seg,
            "Merge tracks inserting segment separators at boundaries",
             NULL, ARGTYPE_BOOL, ARG_NOMINMAX },
+       {TRACKFILTER_FAKETIME_OPTION, &opt_faketime,
+           "Add specified timestamp to each trackpoint",
+             NULL, ARGTYPE_STRING, ARG_NOMINMAX},
        ARG_TERMINATOR
 };
 
@@ -973,6 +979,101 @@ trackfilter_trk2seg(void)
        track_ct = 1;
 }
 
+/*******************************************************************************
+* option: "faketime"
+*******************************************************************************/
+
+typedef struct faketime_s
+{
+       time_t start;
+       int    step;
+       int   force;
+} faketime_t;
+
+static faketime_t
+trackfilter_faketime_check(const char *timestr)
+{
+       int i, j;
+       char fmtstart[20];
+       char fmtstep[20];
+       char c;
+       const char *cin;
+       struct tm time;
+       int timeparse = 1;
+       faketime_t result;
+       result.force = 0;
+
+       i = j = 0;
+       strncpy(fmtstart, "00000101000000", sizeof(fmtstart));
+       strncpy(fmtstep,  "00000000000000", sizeof(fmtstep));
+       cin = timestr;
+
+       while ((c = *cin++))
+       {
+               if (c=='f') {
+                       result.force = 1;
+                       continue;
+               }
+
+               if (c!='+' && isdigit(c) == 0)
+                       fatal(MYNAME "-faketime: invalid character \"%c\"!\n", c);
+
+               if (timeparse) {
+                       if ((c == '+')) {
+                               fmtstart[i++] = '\0';
+                               timeparse = 0;
+                       } else {
+                               if (fmtstart[i] == '\0') fatal(MYNAME "-faketime: parameter too long \"%s\"!\n", timestr);
+                               fmtstart[i++] = c;
+                       }
+               } else {
+                       if (fmtstep[j] == '\0') fatal(MYNAME "-faketime: parameter too long \"%s\"!\n", timestr);
+                       fmtstep[j++] = c;
+               }
+       }
+       fmtstep[j++] = '\0';
+
+       cin = strptime(fmtstart, "%Y%m%d%H%M%S", &time);
+       result.step = atoi(fmtstep);
+       if ((cin != NULL) && (*cin != '\0'))
+           fatal(MYNAME "-faketime-check: Invalid time stamp (stopped at %s of %s)!\n", cin, fmtstart);
+
+       result.start = mkgmtime(&time);
+       return result;
+}
+
+static int
+trackfilter_faketime(void)             /* returns number of track points left after filtering */
+{
+       faketime_t faketime;
+
+       queue *elem, *tmp;
+       int i, dropped, inside = 0;
+
+       if (opt_faketime != 0)
+           faketime = trackfilter_faketime_check(opt_faketime);
+
+       dropped = inside = 0;
+
+       for (i = 0; i < track_ct; i++)
+       {
+           route_head *track = track_list[i].track;
+
+           QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp)
+           {
+               waypoint *wpt = (waypoint *)elem;
+
+                       if (opt_faketime != 0 && (wpt->creation_time == 0 || faketime.force)) {
+                               wpt->creation_time = faketime.start;
+                               faketime.start += faketime.step;
+                       }
+           }
+       }
+
+       return track_pts - dropped;
+}
+
+
 /*******************************************************************************
 * global cb's
 *******************************************************************************/
@@ -1058,6 +1159,20 @@ trackfilter_process(void)
            if ( !opts ) return;
        }
 
+       if ((opt_faketime != NULL))
+       {
+           opts--;
+
+           trackfilter_faketime();
+
+           if (opts == 0) return;
+
+           trackfilter_deinit();       /* reinitialize */
+           trackfilter_init(NULL);
+
+           if (track_ct == 0) return;          /* no more track(s), no more fun */
+       }
+
        if ((opt_stop != NULL) || (opt_start != NULL))
        {
            if (opt_start != NULL) opts--;
diff --git a/xmldoc/filters/options/track-faketime.xml b/xmldoc/filters/options/track-faketime.xml
new file mode 100644 (file)
index 0000000..15955ff
--- /dev/null
@@ -0,0 +1,41 @@
+<para>
+This option assigns a time value to each trackpoint.
+</para>
+<para>
+The value of this option must be in the form of fYYYYMMDDHHMMSS+SS.
+</para>
+<para>
+The parameter f (force) is optional and means that the time value of each trackpoint is replaced.
+If f is not specified, the time value of each trackpoint is only replaced when the trackpoint contains no time value.
+</para>
+<para>
+YYYYMMDDHHMMSS is the pattern for the timestamp and is required.
+</para>
+<para>
+The plus sign is the delimiter between the timestamp and the step time in seconds.
+The first trackpoint receives the time value of the timestamp and
+each following trackpoint receives the timestamp incremented by the step time.
+The specification of the steptime is optional.
+</para>
+<para>
+The parameter was added because some software products (e.g. garmin training center)
+require a time value for each trackpoint.
+</para>
+<example id="ex_track_faketime1">
+<title>Replace time values of a track</title>
+<para>
+Replace all time values with new time values.
+Start at the 5 th of July, 2010 at 8 PM and
+increment 2 seconds between each trackpoint:
+</para>
+<para><userinput>gpsbabel -i kml -f in.kml -x track,faketime=f20100705200000+2 -o gtrnctr -F out.tcx</userinput></para>
+</example>
+<example id="ex_track_faketime2">
+<title>Add time values to a track</title>
+<para>
+Add a time value to a trackpoint, if the trackpoint contains no time value.
+Start at the 6 th of May, 2010 at 6 AM and
+increment 5 seconds between each trackpoint:
+</para>
+<para><userinput>gpsbabel -i kml -f in.kml -x track,faketime=20100506060000+5 -o gtrnctr -F out.tcx</userinput></para>
+</example>